
// class Person {
//   constructor(private _name: string) { }
//   get name() {
//     return this._name + ' zhangsan '
//   }
//   set name(name: string) {
//     console.log('setName', name)
//     this._name = name
//   }
// }
// const person = new Person('nono')
// console.log(person.name)
// person.name = '1111'
// console.log(person.name)



// 单例模式
class Demo {



  private constructor() { }

  static getInstance() {
    return new Demo()
  }
}

const demo1 = Demo.getInstance()



// 访问类型
// private protected public 访问类型

// public 允许我在类的内外被调用
// private 允许我在类的内被使用
// protected 允许在类  内 及继承的子类中使用
// class Person {
//   // private name: string
//   protected name: string
//   // name: string
//   sayHi() {
//     this.name
//     console.log('sayHi')
//   }
// }

// class Teacher extends Person {
//   sayBye() {
//     console.log(this.name)
//   }
// }

// const person = new Person()
// person.name = 'none'
// console.log(person.name)
// person.sayHi()



// constructor
// class Person {
//   // private name: string

//   // 传统写法

//   // public name: string
//   // constructor(name: string) {
//   //   this.name = name
//   // }

//   // 简化写法 等价于
//   constructor(public name: string) { }
// }
// const person = new Person('nono')
// console.log(person.name)



// class Person {
//   constructor(public name: string) {

//   }
// }
// // 在子类中使用constructor 必须调用super
// class Teacher extends Person {
//   constructor(public age: number) {
//     super('nono')
//   }
// }

// const teacher = new Teacher(28)
// console.log(teacher.name)
// console.log(teacher.age)



// // 类的定义与继承 基础类
// // 如果定义一个类型，类的属性定义
// class Person {
//   name = 'nono'
//   getName() {
//     return this.name
//   }
// }

// class Teacher extends Person {
//   getTeacherName() {
//     return 'Teacher'
//   }
//   // 子类把父类的覆盖了  使用  super.getName 可以重新调用父类的方法 
//   getName() {
//     return super.getName() + 'child'
//     // return 'child getName'
//   }
// }

// const teacher = new Teacher()
// console.log(teacher.getName())
// console.log(teacher.getTeacherName())


// const person = new Person()
// console.log(person.getName())



// // interface 和 type 相类似，但并不完全一致
// interface Person {
//   // readonly name:string // 只读属性
//   name: string
//   age?: number  // 可有可无 ?:
//   say(): string
// }

// // 继承
// interface teacher extends Person {
//   teacher(): string
// }

// // 定义函数类型
// interface sayHi {
//   (str: string): string
// }

// const getPersonName = (person: Person) => {
//   console.log(person.name)
// }
// const setPersonName = (person: Person, name: string): void => {
//   person.name = name
// }
// const person = {
//   name: 'nono',
//   sex: 'male',
//   say() {
//     return 'say hello'
//   }
// }
// // 不会报错 通过缓存一个变量再传入，检查就没那么严格不会报错
// getPersonName(person)

// // 会报错  直接以字面量的方式传入就会报错
// getPersonName({ name: 'nono', sex: 'male' })  // XXXXX错误写法

// setPersonName(person, 'nono')

// // 类去使用接口 需调用 implements
// class User implements Person {
//   name = 'none'
//   say() {
//     return 'hello'
//   }
// }

// const say: sayHi = (word: string) => {
//   return 'say hi'
// }



// // 数组
// const numArr: number[] = [1, 2, 3]
// const strArr: string[] = ['a', 'b']
// const arr: (number | string)[] = [1, 2, '111']
// const undefinedArr: undefined[] = [undefined]

// // type alias 类型别名
// type User = { name: string, age: number }

// class Teacher {
//   name: string
//   age: number
// }

// const objectArr: User[] = [
//   new Teacher(),
//   {
//     name: 'nono',
//     age: 20
//   }
// ]

// // 元组 tuple
// // 对数组中的每一项的数据进行约束 

// const teacherInfo: (         number | string)[] = ['nono', 'male', 18]
// const teacherInfos: [string, string, number] = ['nono', 'male', 18]

// // 场景
// const teacherList: [string, string, number][] = [
//   ['aaa', 'male', 19],
//   ['bb', 'femal', 28]
// ]




// // 基础类型
// // boolean, number, string, void, undefined, symbol, null

// // 如果 变量 赋值和声明放在同一行，可以推断出数据类型，否则不能推断类型，需要手动添加注解
// let count: number;
// count = 123


// // 对象类型 {}, Class ,function,[]

// // const func = (str) => { }  js 写法
// const func = (str: string) => {
//   return parseInt(str, 10)
// }
// // “:” 后面跟着类型 “=” 后面指具体的实现
// const func1: (str: string) => number = (str) => {
//   return parseInt(str, 10)
// }


// const date = new Date()

// // 其他的 case 
// interface Person {
//   name: string
// }
// const rawData = "{ 'name': 111 }"
// const newDate: Person = JSON.parse(rawData)


// let temp: number | string = 123
// temp = '456'




// // 定义函数的方式：
// function hellon() { }
// const hellon1 = function () { }
// const hello2 = () => { }

// // 函数返回值的类型需要 注解
// function add(first: number, second: number): number {
//   return first + second
// }
// const total = add(1, 2)

// // void 不应该有返回值
// function sayHello(): void {
//   console.log('hello')
// }

// // never 函数不可能执行完成
// function erroEmitter(): never {
//   throw new Error();
//   // while (true) { }
//   console.log(123)
// }

// // 参数类型注解  解构类型参数的函数注解的写法 必须是 {} : {}
// function addNum({ first, second }: { first: number, second: number }): number {
//   return first + second
// }
// const totalNum = addNum({ first: 1, second: 2 })

// function getTotal({ first }: { first: string }) {
//   return first
// }
// const getFirst = getTotal({ first: '10' })















// // type annotation 类型注解,我们来告诉 TS 变量是什么类型
// // type inference 类型推断, TS 会自动的去尝试分析变量的类型

// // 如果 TS 能够自动分析变量类型，我们就什么也不需要做了
// // 如果 TS 无法分析 变量类型，我们就需要使用类型注解

// // let count: number
// // count = 123
// // let countInference = 123

// const firstNumber = 1
// const secondNumber = 2
// const total = firstNumber + secondNumber













// // 基础类型
// // null、 undefined、symbol、boolean、void
// const count: number = 123
// const userName: string = '姓名'

// // 对象类型
// class Person { }

// const info: {
//   name: string,
//   age: number
// } = {
//   name: '姓名',
//   age: 13
// }

// const numbers: number[] = [1, 2, 3]   // 数组

// const nono: Person = new Person()

// const getTotal: () => number = () => {   // 函数类型，必须返回一个数字
//   return 1234
// }
